//
// Created by QU on 24-9-11.
//
#include <boost/asio.hpp>

#include <iostream>
#include <random>
#include <cstring> // 用于 strlen, memcpy
#include <chrono>  // 用于 sleep_for
#include <thread>  // 用于 this_thread::sleep_for

using namespace std;
using namespace boost::asio::ip;
const int MAX_LENGTH = 1024 * 2;
const int HEAD_LENGTH = 2;

// 随机生成指定长度的字符串
std::string generate_random_string(size_t length)
{
    const char charset[] =
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "0123456789";
    const size_t max_index = sizeof(charset) - 1;

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, max_index - 1);

    std::string random_string;
    random_string.reserve(length);
    for (size_t i = 0; i < length; ++i)
    {
        random_string += charset[dis(gen)];
    }
    return random_string;
}

int main()
{
    try
    {
        //创建上下文服务
        boost::asio::io_context ioc;
        //构造endpoint
        tcp::endpoint remote_ep(address::from_string("127.0.0.1"), 10120);
        tcp::socket sock(ioc);
        boost::system::error_code error = boost::asio::error::host_not_found;;
        sock.connect(remote_ep, error);
        if (error)
        {
            cout << "connect failed, code is " << error.value() << " error msg is " << error.message();
            return 0;
        }

        thread send_thread([&sock]
        {
            for (;;)
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(200));

                // 生成随机字符串
                std::string request = generate_random_string(120);
                std::cout << "Gen str is: \t" << request << std::endl;
                size_t request_length = request.size();
                char send_data[MAX_LENGTH] = { 0 };

                // 复制数据长度和数据到缓冲区
                memcpy(send_data, &request_length, 2);
                memcpy(send_data + 2, request.c_str(), request_length);

                // 发送数据
                boost::asio::write(sock, boost::asio::buffer(send_data, request_length + 2));
            }
        });;

        thread recv_thread([&sock]
        {
            for (;;)
            {
                this_thread::sleep_for(std::chrono::milliseconds(200));

                char reply_head[HEAD_LENGTH];
                size_t reply_length = boost::asio::read(sock, boost::asio::buffer(reply_head, HEAD_LENGTH));
                size_t msglen = 0;
                memcpy(&msglen, reply_head, HEAD_LENGTH);
                char msg[MAX_LENGTH + HEAD_LENGTH] = { 0 };
                size_t msg_length = boost::asio::read(sock, boost::asio::buffer(msg, msglen));
                // size_t msg_length = boost::asio::read(sock, boost::asio::buffer(msg, MAX_LENGTH));

                std::cout << "Reply len is: \t" << msglen << std::endl;
                std::cerr << "Reply str is: \t";
                std::cerr.write(msg, msg_length) << endl;
            }
        });

        send_thread.join();
        recv_thread.join();
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << endl;
    }
    return 0;
}
